package com.cosyhut.blocks.engine;

import com.jme.scene.*;
import com.jme.math.*;
import com.jme.bounding.*;
import com.jme.renderer.*;

import com.cosyhut.blocks.jode.*;
import com.cosyhut.blocks.display.*;
import com.cosyhut.blocks.factory.*;

import java.util.*;

/**
 * 
 * @author TimWorks Jan 24, 2007
 * 
 * A Block repensents a group of ODE Geoms, an ODE space and a debug apperance
 * on jME side. A "block" can be loaded from an XML file or dump to a file.
 */
public class Block {
	MBlock _model;

	// --- ODE
	// locatio, rotation and velocity, mass, etc.
	protected Engine _engine;

	protected ODEBlock _block;

	// -- jME
	// debug presentation
	protected GRenderer _renderer;

	protected Node _root;

	protected boolean _debugFlag = false;

	public Block(MBlock model, Engine engine, GRenderer renderer) {
		this._model = model;
		this._renderer = renderer;
		this._engine = engine;

		// create all the children geoms
		this._root = new Node();

		this._block = new ODEBlock(engine);
		this.createBlock();
//		this.toggleDebug(this._renderer);
	}

	public void toggleDebug(GRenderer renderer) {
		if (true == this._debugFlag) {
			this._debugFlag = false;
			this._root.detachAllChildren();
		} else {
			this._debugFlag = true;
			this._root.attachChild(DVisual.createXYZ(this._renderer
					.getRenderer()));
			// _geoms
			Iterator i = this._block.getGeoms().iterator();
			while (i.hasNext()) {
				ODEGeom g = (ODEGeom) i.next();
				Node vg = DVisual.createNode(g);
				this._root.attachChild(vg);
				vg.setLocalTranslation(g.getPosition());
				vg.setLocalRotation(g.getRotation());
			}

			// _joints
			i = this._block.getJoints().iterator();
			while (i.hasNext()) {
				ODEJoint j = (ODEJoint) i.next();
				Vector3f axis = j.getModel().getAxis();
				Vector3f axis2 = j.getModel().getAxis2();
				if (null != axis) {
					Node vaxis = DVisual.createVector(this._renderer
							.getRenderer(), new Vector3f(0, 0, 0), axis,
							new ColorRGBA(1, 0, 0, 1));
					this._root.attachChild(vaxis);
					vaxis.setLocalTranslation(j.getPosition());
					vaxis.setLocalRotation(j.getRotation());
				}
				if (null != axis2) {
					Node vaxis2 = DVisual.createVector(this._renderer
							.getRenderer(), new Vector3f(0, 0, 0), axis2,
							new ColorRGBA(1, 0, 0, 1));
					this._root.attachChild(vaxis2);
					vaxis2.setLocalTranslation(j.getPosition());
					vaxis2.setLocalRotation(j.getRotation());
				}
			}

			// _jointpoints
			i = this._block.getJointPoints().iterator();
			while (i.hasNext()) {
				ODEJointPoint j = (ODEJointPoint) i.next();
				Node vj = DVisual.createDot(this._renderer.getRenderer());
				this._root.attachChild(vj);
				vj.setLocalTranslation(j.getPosition());
				vj.setLocalRotation(j.getRotation());
			}
		}

		this._renderer.enableDebug(this._root);

		// 3d acceleration
		this._root.setModelBound(new BoundingSphere());
		this._root.updateModelBound();

		this._root.updateGeometricState(-1, false);
	}

	public void update() {
		// update location
		SWIGTYPE_p_float p = jode.new_floatArray(3);
		p = jode.dBodyGetPosition(this._block.getBody());
		this._root.setLocalTranslation(ODEHelper.fromArraytoVector3f(p));

		// update rotation
		SWIGTYPE_p_float r = jode.new_floatArray(12);
		r = jode.dBodyGetRotation(this._block.getBody());
		this._root.setLocalRotation(ODEHelper.fromArraytoMatrix3f(r));
	}

	public void setPosition(Vector3f p) {
		this._block.setPosition(p);
	}

	public void setRotation(Matrix3f r) {
		this._block.setRotation(r);
	}

	// --------------------------------------------------------------------------
	public Node getRoot() {
		return this._root;
	}

	public Vector3f getPosition() {
		return this._block.getPosition();
	}

	public Matrix3f getRotation() {
		return this._block.getRotation();
	}

	public ODEBlock getBlock() {
		return this._block;
	}

	public ODEWorld getWorld() {
		return this._engine.getWorld();
	}

	public MBlock getModel() {
		return this._model;
	}

	// --------------------------------------------------------------------------
	private void createBlock() {
		BFactory f = BFactory.get();

		// _geoms
		Iterator i = this._model.getGeoms().iterator();
		while (i.hasNext()) {
			MNode n = (MNode) i.next();
			ODEGeom g = f.createGeom(n.getName());
			Vector3f p = n.getPosition();
			Matrix3f r = n.getRotation();
			this._block.addGeom(g, p, r);
		}

		// _joints
		i = this._model.getJoints().iterator();
		while (i.hasNext()) {
			MNode n = (MNode) i.next();
			ODEJoint j = f.createJoint(n.getName());
			Vector3f p = n.getPosition();
			Matrix3f r = n.getRotation();
			this._block.addJoint(j, p, r);
		}

		// _jointpoints
		i = this._model.getJointPoints().iterator();
		while (i.hasNext()) {
			MNode n = (MNode) i.next();
			ODEJointPoint jp = f.createJointPoint();
			Vector3f p = n.getPosition();
			Matrix3f r = n.getRotation();
			this._block.addJointPoint(jp, p, r);
		}
	}
}
